using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.BizTalk.TransportProxy.Interop;
using Microsoft.BizTalk.Message.Interop;

namespace Microsoft.Samples.BizTalk.Adapter.Tcp
{
    /// <summary>
    ///     This class implements a wrapper for a batch message.
    /// </summary>
    /// <author>
    ///     Paul Brown
    /// </author>
    public class BatchMessage
    {
        #region Private Instance Members

        private IBaseMessage        _message;           // The message submitted to the batch
        private IBaseMessage        _solicitMessage;    // The solicit message associated with this message if there is one
        private BatchOperationType  _opType;            // The batch operation type of this message when it was submitted
        private string              _correlationToken;  // The unique correlation token used to correlate responses back to requests
        private DateTime            _responseExpiration;// The expiration time of a response associated with a request
        private Exception           _messageException;  // The exception associated with the message (when suspending)
        private IBTTransmitter      _callback;          // The IBTTransmitter object used to callback with a response
        private int                 _order;             // A value (one based) that specifies the order of this message in this batch

        #endregion

        #region Constructor

        /// <summary>
        ///     This constructor initializes the instance.
        /// </summary>
        public BatchMessage(IBaseMessage message)
        {
            this.InternalCtor(message, null, string.Empty, DateTime.MinValue, null, null);
        }

        /// <summary>
        ///     This constructor initializes the instance.
        /// </summary>
        public BatchMessage(IBaseMessage message, Exception e)
        {
            // Validate
            if (e == null) throw new ArgumentNullException("e");

            // Call internal constructor
            this.InternalCtor(message, null, string.Empty, DateTime.MinValue, null, e);
        }

        /// <summary>
        ///     This constructor initializes the instance.
        /// </summary>
        public BatchMessage(IBaseMessage message, IBaseMessage solicitMessage)
        {
            // Validate
            if (solicitMessage == null) throw new ArgumentNullException("solicitMessage");

            // Call internal constructor
            this.InternalCtor(message, solicitMessage, string.Empty, DateTime.MinValue, null, null);
        }

        /// <summary>
        ///     This constructor initializes the instance.
        /// </summary>
        public BatchMessage(IBaseMessage message, string correlationToken, DateTime responseExpiration, IBTTransmitter callback)
        {
            // Validate
            if (callback == null) throw new ArgumentNullException("callback");

            // Call internal constructor
            this.InternalCtor(message, null, correlationToken, responseExpiration, callback, null);
        }

        /// <summary>
        ///     This is the internal implementation of the constructor.
        /// </summary>
        private void InternalCtor(IBaseMessage message, IBaseMessage solicitMessage, string correlationToken, DateTime responseExpiration, IBTTransmitter callback, Exception e)
        {
            // Validate arguments
            if (message == null) throw new ArgumentNullException("message");
            if (correlationToken == null) throw new ArgumentNullException("correlationToken");

            // Initialize
            this._message = message;
            this._solicitMessage = solicitMessage;
            this._correlationToken = correlationToken;
            this._responseExpiration = responseExpiration;
            this._messageException = e;
            this._callback = callback;
            this._opType = BatchOperationType.MoveToSuspendQ;
            this._order = 0;
        }

        #endregion

        #region Public Instance Properties

        /// <summary>
        ///     This property returns the message submitted to the batch.
        /// </summary>
        public IBaseMessage Message
        {
            get { return (this._message); }
        }

        /// <summary>
        ///     This property returns the solicit message received from BizTalk that is the pair of the response message
        ///     identified by the property Message.  If this batch message is not associated with a solicit/response pair then
        ///     this property will return null.
        /// </summary>
        public IBaseMessage SolicitMessage
        {
            get { return (this._solicitMessage); }
        }

        /// <summary>
        ///     This property returns the correlation token used to correlate a response to the request.  If this batch
        ///     message is not associated with a request/response pair then this property will return an empty string.
        /// </summary>
        public string CorrelationToken
        {
            get { return (this._correlationToken); }
        }

        /// <summary>
        ///     This property returns the expiration datetime used by the messaging engine to discard responses if the
        ///     expiration date has passed.
        /// </summary>
        public DateTime ResponseMessageExpiration
        {
            get { return (this._responseExpiration); }
        }

        /// <summary>
        ///     This property gets or sets the exception used by the messaging engine when a message is suspended.
        /// </summary>
        public Exception MessageException
        {
            get { return (this._messageException); }
            set { this._messageException = value; }
        }

        /// <summary>
        ///     This property returns the callback object used by the messaging engine to pass messages to be delivered.
        /// </summary>
        public IBTTransmitter TransmitterCallback
        {
            get { return (this._callback); }
        }

        /// <summary>
        ///     This property gets or sets the batch operation performed on the message.
        /// </summary>
        public BatchOperationType BatchOperationType
        {
            get { return (this._opType); }
            set { this._opType = value; }
        }

        /// <summary>
        ///     This property gets or sets the order of the message in the batch.  It is used to create a batch for resubmission
        ///     after failure that follows the original order.
        /// </summary>
        public int MessageOrder
        {
            get { return (this._order); }
            set { this._order = value; }
        }

        #endregion
    }
}
